package top.mcwebsite.playandroid.lib.task

import android.util.Log
import java.util.Comparator
import java.util.PriorityQueue
import java.util.Queue

/**
 * 任务链
 */
class TaskChain {

    internal var initParams: Map<String, Any>? = null
    internal val tasks: MutableMap<String, TaskNode> = mutableMapOf()
    internal lateinit var taskQueue: Queue<TaskNode>
    private var isStarted = true


    fun initParams(initParams: Map<String, Any>): TaskChain {
        this.initParams = initParams
        return this
    }

    fun doOnIO(block: suspend (TaskContext) -> Any): TaskChain {
        val task = task {
            job = block
            dispatchMode = DispatchMode.IO
        }
        return addTask(task)
    }

    fun doOnMain(block: suspend (TaskContext) -> Any): TaskChain {
        val task = task {
            job = block
            dispatchMode = DispatchMode.MAIN
        }
        return addTask(task)
    }


    fun addTask(task: Task): TaskChain {
        tasks[task.name] = TaskNode(task)
        if (!isStarted) {
            // TODO
        }
        return this
    }

    fun start(dispatcher: TaskDispatcher = TaskManager.getTaskDispatcher()): TaskChainController {
        // 构建有向无环图
        if (::taskQueue.isInitialized) {
            throw IllegalStateException("不能重复构建 Task DAG")
        }
        buildDAG()
        val taskChainController = dispatcher.dispatch(this)
        taskChainController.start()
        return taskChainController
    }

    private fun buildDAG() {
        taskQueue = PriorityQueue()
        taskQueue.addAll(tasks.filter { it.value.task.dependsOn.isNullOrEmpty() }.map { it.value })
        tasks.filter { !it.value.task.dependsOn.isNullOrEmpty() }.forEach { (_, taskNode) ->
            taskNode.task.dependsOn!!.forEach { dependsTaskName ->
                tasks[dependsTaskName].apply {
                    if (TaskManager.isDebug()) {
                        Log.w("TaskManager", "${taskNode.task.name} 依赖的 $dependsTaskName 任务不存在")
                    }
                }?.also {
                    if (it.nextTasks == null) {
                        it.nextTasks = PriorityQueue()
                    }
                }?.nextTasks?.add(taskNode)

            }
        }
        if (TaskManager.isDebug()) {
            // 检查是否有环
        }
    }
}